module Reserved = Ada_lexical.Reserved;;
module Attribute = Ada_lexical.Attribute;;
module Pragma = Ada_lexical.Pragma;;

module Integer = struct
	type t = int;;
	let zero = 0;;
	let scaling ~base ~adjustment x = x * int_of_float (float_of_int base ** float_of_int adjustment);;
	let of_basedstring ~base s = (
		let rec loop base s i r = (
			if i >= String.length s then (
				r
			) else (
				let hex = "0123456789ABCDEF" in
				let n = String.index hex s.[i] in
				loop base s (succ i) (r * base + n)
			)
		) in
		loop base (String.uppercase s) 0 0
	);;
	let pp ~(quali: bool) ~(paren: bool) (f: Format.formatter) (x: t): unit = (
		if paren && x < 0 then Format.pp_print_char f '(';
		Format.pp_print_int f x;
		if paren && x < 0 then Format.pp_print_char f ')'
	);;
end;;

module Real = struct
	type t = float;;
	let zero = 0.0;;
	let scaling ~base ~adjustment x = x *. (float_of_int base ** float_of_int adjustment);;
	let of_basedstring ~base s = (
		if base = 10 then float_of_string s else (
			let p = String.index s '.' in
			let integer_part = String.sub s 0 p in
			let decimal_part = String.sub s (succ p) (String.length s - p - 1) in
			let n = Integer.of_basedstring ~base (integer_part ^ decimal_part) in
			let m = (float_of_int base) ** float_of_int (String.length decimal_part) in
			float_of_int n /. m
		)
	);;
	let pp ~(quali: bool) ~(paren: bool) (f: Format.formatter) (x: t): unit = (
		if paren && x < 0.0 then Format.pp_print_char f '(';
		Format.pp_print_float f x;
		if paren && x < 0.0 then Format.pp_print_char f ')'
	);;
end;;

module Token = Ada_lexical.Element (Integer) (Real)
	(struct
		let element_module = "Lexical.Token";;
		let reserved_module = "Lexical.Reserved";;
		let attribute_module = "Lexical.Attribute";;
		let pragma_module = "Lexical.Pragma";;
	end);;
